﻿using System;
using System.Collections.Generic;
using System.Configuration.Install;
using System.Linq;
using System.Reflection;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using GrayParrot.Extensions.Types;

namespace GrayParrot.ServiceProcess
{
    public class GrayParrotService<T> : ServiceBase where T : class
    {
        //Type m_implementer = null;

        public GrayParrotService()
        {
            //m_implementer = implementer;

            ConfigureServiceFromAttributes();
        }

        private void ConfigureServiceFromAttributes()
        {
            var attribute = this.GetType().GetAttribute<WindowsServiceAttribute>();

            if (attribute != null)
            {
                //EventLog.Source = string.IsNullOrEmpty(attribute.EventLogSource) ? "GrayParrotService" : attribute.EventLogSource;

                CanStop = attribute.CanStop;
                CanPauseAndContinue = attribute.CanPauseAndContinue;
                CanShutdown = attribute.CanShutdown;

                // we don't handle: laptop power change event
                CanHandlePowerEvent = false;

                // we don't handle: Term Services session event
                CanHandleSessionChangeEvent = false;

                // always auto-event-log 
                AutoLog = true;
            }
            else
            {
                throw new InvalidOperationException(
                    string.Format("GrayParrotService implementer {0} must have a WindowsServiceAttribute.",
                                  typeof(T).FullName));
            }
        }

        private static bool IsServiceInstalled()
        {
            string m_serviceName = string.Empty;

            var attribute = typeof(T).GetAttribute<WindowsServiceAttribute>();
            if (attribute != null)
            {
                m_serviceName = attribute.DisplayName;
            }

            return ServiceController.GetServices().Any(s => s.ServiceName == m_serviceName);
        }

        private static void InstallService()
        {
            if (IsServiceInstalled())
            {
                UninstallService();
            }

            ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetExecutingAssembly().Location });
        }

        private static void UninstallService()
        {
            ManagedInstallerClass.InstallHelper(new string[] { "/u", Assembly.GetExecutingAssembly().Location });
        } 
    }
}
